May 2, 2025

Chebyshev's Bias (C++)

A slightly uneven spread; pushed by Riemann's Zeta

DownloadOpen

Chebyshev's Bias is likely to be quite important in the end (when Riemann is proven or disproven). It seems to be the best simple example of the fact that there is some asymmetric disturbance happening with prime numbers.

All primes except 2 are odd and divisible by 4 with a remainder. They can be categorised by remainder group and in theory there should be perfectly equal spread.

  • 4k + 1: Primes congruent to 1 mod 4 (e.g., 5, 13, 17).
  • 4k + 3: Primes congruent to 3 mod 4 (e.g., 3, 7, 11).
  • Spread is not equal though. The 4k +3 group normally wins.

    Chebyshev's Bias

    It's the Riemann Zeta function that is giving 4 k + 3 its push. Although we can't prove it yet.

    The code is quite simple it takes the first 50 milliion primes and computes the bias. Just remember to point the code to the the file 50mprimes.txt which you can download on our website.

    #include <iostream>
    #include <fstream>
    #include <string>
    #include <unordered_map>
    #include <iomanip>
    
    using namespace std;
    
    int main() {
        string filename = "/cpp/primelist/50mprime.txt";
        ifstream file(filename);
    
        if (!file.is_open()) {
            cout << "Failed to open the file." << endl;
            return 1;
        }
    
        unordered_map<int, int> digit_counts;
        int total_count = 0;
    
        int prime;
        while (file >> prime) {
            int last_digit = prime % 10;
            if (last_digit == 3 || last_digit == 7 || last_digit == 9 ||
                last_digit == 1 || last_digit == 2 || last_digit == 5) {
                digit_counts[last_digit]++;
                total_count++;
            }
        }
    
        file.close();
    
        cout << "Digit\tCount\tPercentage" << endl;
    
        for (const auto& pair : digit_counts) {
            int digit = pair.first;
            int count = pair.second;
            double percentage = (count * 100.0) / total_count;
    
            cout << digit << "\t" << count << "\t";
            cout << fixed << setprecision(8) << percentage << "%" << endl;
        }
    
        return 0;
    }


    The output file should look a bit like this, with remainders 1 and 5 rather ruining the beauty of the table.

    You could modify the code to exclude them from the print though.